# -*- coding: utf-8 -*-
# @Time    : 2022/11/16 15:13
# @Author  : yangyuexiong
# @Email   : yang6333yyx@126.com
# @File    : main.py
# @Software: PyCharm


from openpyxl import Workbook
from openpyxl.cell.cell import Cell

from commands.app_commands.Excel.excel_base.main import ExcelHandle, write_range_tuple


class ExcelWriteHandle(ExcelHandle):
    """写入"""

    def __init__(self, excel_path=None):
        super(ExcelWriteHandle, self).__init__(excel_path=excel_path)

        self.write_range_dict = {
            "cell": self.write_cell,
            "a_line": self.write_a_line,
            "one_column": self.write_one_column,
            "custom_range": self.write_custom_range,
            "write_coordinate": self.write_coordinate,
        }

    def check_content(self, content):
        """检验写入内容类型"""

        if not isinstance(content, list):
            msg = f'写入失败：写入一行内容接收的是一个list,而不是一个: {type(content)} '
            print(msg)
            self.throw['status'] = False
            self.throw['message'] = msg
            return False
        return True

    def write_cell(self, sheet, row_num, column_num, **kwargs):
        """
        写入单元格数据
        :param sheet: sheet对象
        :param row_num: 行号
        :param column_num: 列号
        :param kwargs:
        :return:
        """

        print('=== write_cell ===')
        cell = f"{column_num}{row_num}"
        content = kwargs.get('content')
        is_save_as = kwargs.get('is_save_as', False)
        new_path = kwargs.get('new_path')

        try:
            if self.debug:
                print(sheet[cell])
                print(f'content:{content}')
            sheet[cell].value = content
        except BaseException as e:
            msg = f'写入:excel单元格: {cell} 失败'
            print(msg)
            self.throw['status'] = False
            self.throw['message'] = msg
            return False

        self.excel_save_as(is_save_as=is_save_as, new_path=new_path)

    def write_a_line(self, sheet, row_num, **kwargs):
        """

        写入一行数据
        :param sheet: sheet对象
        :param row_num: 行号
        :param kwargs:
        :return:
        """

        print('=== write_a_line ===')
        sheet_rows = list(sheet.rows)
        max_row = sheet.max_row
        content = kwargs.get('content')
        is_save_as = kwargs.get('is_save_as', False)
        new_path = kwargs.get('new_path')
        rn = int(row_num)

        if self.debug:
            print(rn, max_row)

        # print(sheet.merged_cells, type(sheet.merged_cells))
        # mc_list = [i for i in sheet.merged_cells]

        if not self.check_content(content):
            return self.throw

        if rn == 0 or rn - 1 > max_row:
            msg = f'写入失败：写入行号不能大于最大行数 {max_row} 或不能少于 0 '
            if self.debug:
                print(msg)
            self.throw['status'] = False
            self.throw['message'] = msg
            return False

        content_index = 0
        # merge_cell_index = 0
        for index, cell in enumerate(sheet_rows[rn - 1]):
            if self.debug:
                print(cell, type(cell))
            coordinate = cell.coordinate
            value = cell.value

            try:
                ready_content = content[content_index]
            except:
                ready_content = ""

            if isinstance(cell, Cell):  # 普通单元格
                if self.debug:
                    print(f'普通的单元格:{coordinate}-{value}')

                if index <= len(content):
                    cell.value = ready_content
                else:
                    cell.value = ready_content

                content_index += 1

            else:  # 合并的单元格-后续需要再独立处理
                pass
            #     try:
            #         current_mc = str(mc_list[merge_cell_index])
            #         print('合并的单元格', current_mc, type(current_mc))
            #         merge_cell_index += 1
            #         l, r = current_mc.split(":")  # ['B23', 'G23']
            #         if l not in success_cell:
            #             sheet.merge_cells(current_mc)
            #             sheet[l] = ready_content
            #     except BaseException as e:
            #         print(f'获取合并单元格对象失败:{e}')

        self.excel_save_as(is_save_as=is_save_as, new_path=new_path)

    def write_one_column(self, sheet, column_num, **kwargs):
        """

        写入一列数据
        :param sheet: sheet对象
        :param column_num: 列号
        :param kwargs:
        """

        print('=== write_one_column ===')
        sheet_columns = list(sheet.columns)
        content = kwargs.get('content')
        is_save_as = kwargs.get('is_save_as', False)
        new_path = kwargs.get('new_path')

        if not self.check_content(content):
            return self.throw

        col_index = None
        for index, i in enumerate(sheet_columns):
            if i[0].coordinate == f'{column_num}1':
                print(i)
                col_index = index
                break

        if not col_index:
            msg = f'写入失败：写入列号：{column_num} 不存在'
            if self.debug:
                print(msg)
            self.throw['status'] = False
            self.throw['message'] = msg
            return False

        content_index = 0

        for index, cell in enumerate(sheet_columns[col_index]):
            if self.debug:
                print(cell)
            coordinate = cell.coordinate
            value = cell.value

            try:
                ready_content = content[content_index]
            except:
                ready_content = ""

            if isinstance(cell, Cell):  # 普通单元格
                if self.debug:
                    print(f'普通的单元格:{coordinate}-{value}')

                if index <= len(content):
                    cell.value = ready_content
                else:
                    cell.value = ready_content

                content_index += 1

        self.excel_save_as(is_save_as=is_save_as, new_path=new_path)

    def write_custom_range(self, sheet, **kwargs):
        """

        写入自定义区间
        :param sheet: sheet对象
        :param kwargs: 起始行列，末尾行列
            content从左往右逐行写入
            {
                "start_row_num":"1",
                "start_column_num":"A",
                "end_row_num":"3",
                "end_column_num":"C",
                "content": ["哈哈1", "哈哈2", "哈哈3", "嗯嗯1", "嗯嗯2", "嗯嗯3"]
            }
        """

        print('=== write_custom_range ===')
        start_row_num = int(kwargs.get('start_row_num'))
        start_column_num = kwargs.get('start_column_num')
        end_row_num = int(kwargs.get('end_row_num'))
        end_column_num = kwargs.get('end_column_num')
        content = kwargs.get('content')
        is_save_as = kwargs.get('is_save_as', False)
        new_path = kwargs.get('new_path')

        if not self.check_content(content):
            return self.throw

        try:
            obj_list = sheet[f'{start_column_num}{start_row_num}':f'{end_column_num}{end_row_num}']
        except BaseException as e:
            msg = f'写入失败：自定义区间错误，请检查'
            self.throw['status'] = False
            self.throw['message'] = msg
            return False

        content.reverse()

        for tup in obj_list:
            for cell in tup:
                # print(cell, type(cell))
                coordinate = cell.coordinate
                value = cell.value
                if isinstance(cell, Cell):  # 普通单元格
                    if self.debug:
                        print(f'普通的单元格:{coordinate}-{value}')
                    try:
                        new_value = content.pop()
                        cell.value = new_value
                    except:
                        cell.value = ''

        self.excel_save_as(is_save_as=is_save_as, new_path=new_path)

    def write_coordinate(self, sheet, **kwargs):
        """

        按坐标写入
        :param sheet: sheet对象
        :param kwargs: 起始行列，末尾行列
            content从左往右逐行写入
            {
                "content": [
                    {"coordinate": "A1", "value": "内容1"},
                    {"coordinate": "B3", "value": "内容2"},
                    {"coordinate": "C2", "value": "内容3"}
                ]
            }
        """

        print('=== write_coordinate ===')
        content = kwargs.get('content', [])
        is_save_as = kwargs.get('is_save_as', False)
        new_path = kwargs.get('new_path')

        try:
            for index, cont in enumerate(content, 1):
                # print(cont)
                coordinate = cont.get("coordinate")
                value = cont.get("value")
                if coordinate:
                    sheet[coordinate].value = value
        except BaseException as e:
            msg = f'写入:excel单元格失败-{e}'
            self.throw['status'] = False
            self.throw['message'] = msg
            return False

        self.excel_save_as(is_save_as=is_save_as, new_path=new_path)

    def excel_write(self, sheet_name=None, write_range=None, **kwargs):
        """
        写入
        :param sheet_name: sheet名称
        :param write_range: 范围类型
        :param kwargs: 对应范围类型的扩展参数
        :return:

        cell:
            行号，列号
            {
                "row_num":"1",
                "column_num":"A",
            }
        a_line:
            行号
            {
                "row_num":"1"
            }
        one_column:
            列号
            {
                "column_num":"A",
            }
        custom_range:
            起始行列，末尾行列
            {
                "start_row_num":"1",
                "start_column_num":"A",
                "end_row_num":"3",
                "end_column_num":"C",
            }
        all:
            全表
            {}
        """
        try:
            if isinstance(self.wb, Workbook):

                print(f"读取:{self.excel_path.split('/')[-1]}")

                if write_range not in write_range_tuple:
                    msg = f'写入范围错误:{write_range}'
                    print(msg)
                    self.throw['status'] = False
                    self.throw['message'] = msg
                    return self.throw

                if not self.check_sheet_name(sheet_name):
                    return self.throw

                sheet = self.get_sheet(sheet_name)
                kwargs['sheet'] = sheet
                write_func = self.write_range_dict.get(write_range)
                write_func(**kwargs)
                return self.throw

        except BaseException as e:
            print(e)
            self.return_error_file()
            return self.throw
